<?php
namespace app\index\controller;
use think\Config;
use Exception;
use think\Db;
use Process\RedisClient;
use think\Request;
class Index
{
    protected $post_data ;

    protected $redis_conf ;

    protected $redis_client ;

    protected $mobile_content_type = [
        0=>'hangye',
        1=>'yingxiao',
    ];

    protected $email_content_type = [
        2=>'html',
    ];

    /**
     * 基础数据校验
     * Index constructor.
     */
    public function __construct()
    {
        $code = 0 ;
        $append_msg = '';
        try{
            $this->post_data = file_get_contents('php://input');
            #$this->post_data = '{"time":1516436566,"msg_type":"mobile","data":[{"to":"15997457695","content":"测试短信测试断刺测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你你"},{"to":"15997457695","content":"测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你"},{"to":"15997457695","content":"测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信测试断刺你测试短信试"}],"timely":"0","content_type":"yx","sms_service":"santong","sign":"【熊猫】"}';
            if(!$this->post_data)
            {
                $code = 10001 ;
                goto end ;
            }
            $this->post_data = json_decode($this->post_data,true);
            if(json_last_error())
            {
                $code = 10002;
                goto end ;
            }
            if(!$this->post_data)
            {
                $code = 10003;
            }
            $this->redis_conf = Config::get('redis');
            $this->redis_client = new RedisClient($this->redis_conf);
            if(empty($this->post_data['msg_type']))
            {
                $code = 10004;
                goto end;
            }
            if(!isset($this->post_data['content_type']) || !is_numeric($this->post_data['content_type']))
            {
                $code = 10005 ;
                goto end;
            }
            if(!is_array($this->post_data['data']))
            {
                $code = 10006;
                goto end;
            }
            if(count($this->post_data['data']) <=0)
            {
                $code = 10007 ;
                goto end ;
            }
            if(empty($this->post_data['time']) || !is_numeric($this->post_data['time']))
            {
                $code = 10008;
                goto end;
            }
            if(stripos($this->post_data['msg_type'] ,'email') !==false )
            {
                $this->post_data['msg_type'] = 'email';
                if(isset($this->email_content_type[$this->post_data['content_type']]))
                {
                    $this->post_data['content_type'] = $this->email_content_type[$this->post_data['content_type']];
                }
                else
                {
                    $code = 10009;
                    $append_msg = "{$this->post_data['content_type']}";
                    goto end ;
                }
            }
            elseif(stripos($this->post_data['msg_type'] ,'mobile') !==false )
            {
                $this->post_data['msg_type'] = 'mobile';
                if(isset($this->mobile_content_type[$this->post_data['content_type']])  )
                {
                    $this->post_data['content_type'] = $this->mobile_content_type[$this->post_data['content_type']] ;
                }
                else
                {
                    $code = 10009;
                    $append_msg = "{$this->post_data['content_type']}";
                    goto end ;
                }
            }
            else
            {
                $code = 10009;
                $append_msg = "[{$this->post_data['msg_type']}]";
                goto end ;
            }
            //获取client
            $this->post_data['client'] = empty($_SERVER['API_CLIENT'])?'unknow':$_SERVER['API_CLIENT'];
        }
        catch(Exception $e)
        {
            $code = 40000 ;
            $append_msg = $e->getMessage();
        }
        end:
        if($code)
        {
            $this->codeReturn($code,$append_msg);
            exit;
        }
    }

    /**
     * 短信发送服务请求入口
     */
    public function index()
    {
        [$code,$append_msg] = $this->{$this->post_data['msg_type']}($this->post_data['data'],$this->post_data['content_type'],empty($this->post_data['timely'])?0:1);
        $this->codeReturn($code , $append_msg);
    }

    /**
     * 短信
     * @param $data
     * @param $channel
     * @param bool $timely
     * @return array
     */
    protected function mobile($data ,$channel,$timely=false)
    {
        # 服务商
        $return  = [0,''];
        try{
            //短信发送数据校验
            if(!empty($this->post_data['sms_service']))
            {
                $sms_service_list = $this->redis_client->get(MOBILE_API_SETTING_CACHE);
                if(empty($sms_service_list))
                {
                    $return[0] = 10010 ;
                    goto end ;
                }
                $sms_service_list = json_decode($sms_service_list,true);
                $appoint_api = '';
                foreach($sms_service_list as $k=>$v)
                {
                    if(stripos($k,$this->post_data['sms_service'])!==false && stripos($k,$this->post_data['content_type'])!==false)
                    {
                        if($v['status']!=1)
                        {
                            $return[0] = 10011;
                            $return[1] = "{$this->post_data['sms_service']}";
                            goto end ;
                        }
                        $appoint_api = $v['api'];
                        break;
                    }
                }
                $this->post_data['sms_service'] = $appoint_api ;
                if(!$this->redis_client->hExists(MOBILE_CONF_TYPE,"{$this->post_data['sms_service']}&{$this->post_data['content_type']}"))
                {
                    $return[0] = 10012;
                    goto end;
                }
            }
            else
            {
                $this->post_data['sms_service'] = '';
            }
            # 签名数据
            if(empty($this->post_data['sign']))
            {
                $sign = $this->redis_client->get(MOBILE_DEFAULT_SIGN_CACHE);
                if(!$sign)
                {
                    throw new Exception('系统默认短信签名已经损坏');
                }
                $sign = json_decode($sign,true);
                $this->post_data['sign'] = trim($sign['default']);
                if(empty($this->post_data['sign']))
                {
                    throw new Exception('系统默认短信签名已经损坏');
                }
            }
            $save_data = [];
            foreach($data as $k=>$v)
            {
                if(empty($v['to']))
                {
                    $return[0] = 10013;
                    goto end ;
                }
                $v['to'] = trim($v['to']);
                $v['to'] = trim($v['to'],',');
                if(!$v['to'])
                {
                    $return[0] = 10014 ;
                    goto end ;
                }
                $to_arr = explode(',', $v['to']);
                if(count($to_arr)>500) // 每条短信发送给定的号码不能超过500
                {
                    $return[0] = 10015;
                    goto end ;
                }
                foreach($to_arr as $m)
                {
                    if(!preg_match('/1[34578][0-9]{9}/', $m))
                    {
                        $return[0] = 10016;
                        goto end ;
                    }
                }
                $v['to'] = join(',',$to_arr);
                $v['template'] = trim($v['template']) ;
                if(empty($v['template']))
                {
                    $return[0] = 10017 ;
                    goto end ;
                }
                //模板指定
                $v['template'] = (int)($v['template']) ;
                if(!$v['template'])
                {
                    $return[0] = 10018 ;
                    goto end ;
                }
                //获取模板变量定义
                $mobile_template_data = json_decode($this->redis_client->hGet(MOBILE_TEMPLATE, $v['template']),true) ;
                if( !$mobile_template_data )
                {
                    $return[0] = 10019 ;
                    goto end ;
                }
                if($mobile_template_data['var_content'])
                {
                    if(!is_array($v['var_content']))
                    {
                        $return[0] = 10020 ;
                        goto end ;
                    }
                    if(count($mobile_template_data['var_content']) != count($v['var_content']))
                    {
                        $return[0] = 10021 ;
                        goto end ;
                    }
                    foreach($v['var_content'] as $m)
                    {
                        if(is_array($m))
                        {
                            $return[0] = 10020 ;
                            goto end ;
                        }
                    }
                    unset($m);
                }
                else{
                    $v['var_content'] = '';
                }

                // 变量指定
                $save_data[] = array(
                    'to'=>$v['to'],
                    'request_client'=>$this->post_data['client'],
                    'var_content'=>$v['var_content'],
                    'template'=>$v['template'],
                    'channel'=>$channel,
                    'api_time'=>$this->post_data['time'],
                    'add_time'=>time(),
                    'sign'=>$this->post_data['sign'],
                    'appoint_api'=>$this->post_data['sms_service'],
                );
            }
            unset($k,$to_arr,$v,$data);
            //入库逻辑
            if($timely)
            {
                $method = 'priorityPush';
            }
            else
            {
                $method = 'Push';
            }
            // redis 队列
            $this->redis_client->multi();
            foreach($save_data as $v)
            {
                $this->redis_client -> {$method}(MOBILE_QUEUE, json_encode($v,JSON_UNESCAPED_UNICODE)) ;
            }
            if(!$this->redis_client->exec())
            {
                throw new Exception('redis transaction error!');
            }
        }
        catch (Exception $e)
        {
            $return[0] = 40000;
            $return[1] = $e->getMessage();
        }
        end:
        return $return;
    }

    /**
     * 邮件
     * @param $data
     * @param $channel
     * @param bool $timely
     * @return array
     */
    protected function email($data,$channel,$timely = false )
    {
        $return  = [0,''];
        try{
            if(empty($this->post_data['sign']))
            {
                $this->post_data['sign'] = '' ;
            }
            else
            {
                $this->post_data['sign'] = trim($this->post_data['sign']) ;
            }
            $save_data = [];
            foreach ($data as $v)
            {
                if(empty($v['to']))
                {
                    $return[0] = 20001;
                    goto end ;
                }
                $v['to'] = trim($v['to']);
                $v['to'] = trim($v['to'],',');
                if(!$v['to'])
                {
                    $return[0] = 20002 ;
                    $return[1] = $v['to'] ;
                    goto end ;
                }
                $to_arr = explode(',', $v['to']);
                if(count($to_arr)>500)
                {
                    $return[0] = 20003;
                    goto end ;
                }
                foreach($to_arr as $email)
                {
                    if(!preg_match('/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/', $email))
                    {
                        $return[0] = 20002;
                        $return[1] = $email;
                        goto end ;
                    }
                }
                $v['to'] = join(',',$to_arr);
                if(empty($v['template']))
                {
                    $return[0] = 20004;
                    goto end ;
                }
                if(!is_numeric($v['template']))
                {
                    $return[0] = 20005;
                    goto end ;
                }
                $email_template_data = json_decode($this->redis_client->hGet(EMAIL_TEMPLATE, $v['template']),true);
                if(!$email_template_data)
                {
                    $return[0] = 20006;
                    goto end ;
                }
                if($email_template_data['var_content'])
                {
                    if(empty($v['var_content']))
                    {
                        $return[0] = 20007;
                        goto end ;
                    }
                    if(!is_array($v['var_content']))
                    {
                        $return[0] = 20008;
                        goto end ;
                    }
                    if(count($email_template_data['var_content'])!=count($v['var_content']))
                    {
                        $return[0] = 20009;
                        goto end ;
                    }
                    foreach($v['var_content'] as $m)
                    {
                        if(is_array($m))
                        {
                            $return[0] = 20008;
                            goto end ;
                        }
                    }
                    unset($m);
                }
                else
                {
                    $v['var_content'] = '';
                }
                if($email_template_data['var_title'])
                {
                    if(empty($v['var_title']))
                    {
                        $return[0] = 20010;
                        goto end ;
                    }
                    if(!is_array($v['var_title']))
                    {
                        $return[0] = 20011;
                        goto end ;
                    }
                    if(count($email_template_data['var_title'])!=count($v['var_title']))
                    {
                        $return[0] = 20012;
                        goto end ;
                    }
                    foreach($v['var_title'] as $m)
                    {
                        if(is_array($m))
                        {
                            $return[0] = 20011;
                            goto end ;
                        }
                    }
                    unset($m);
                }
                else
                {
                    $v['var_title'] = '';
                }
                $save_data[] = [
                    'api_time'       => $this->post_data['time'],
                    'request_client' => $this->post_data['client'],
                    'template'=>$v['template'],
                    'sign'=>$this->post_data['sign'],
                    'to'=>$v['to'],
                    'var_title'=>$v['var_title'],
                    'var_content'=>$v['var_content'],
                    'add_time'=>time(),
                ];
            }
            if($timely)
            {
                $method = 'priorityPush';
            }
            else
            {
                $method = 'Push';
            }

            $this->redis_client->multi();
            foreach($save_data as $v)
            {
                $this->redis_client -> {$method}(EMAIL_QUEUE, json_encode($v,JSON_UNESCAPED_UNICODE)) ;
            }
            if(!$this->redis_client->exec())
            {
                throw new Exception('redis transaction error!');
            }
        }
        catch(Exception $e)
        {
            $return[0] = 40000;
            $return[1] = $e->getMessage();
        }
        end:
        return $return;
    }

    /**
     * 返回结果
     * @param $code
     * @param bool|string $append_msg
     */
    protected function codeReturn($code,$append_msg=false )
    {
        global $ERROR_CODE_INFO ;
        $this->jsonReturn(array('error'=>$code,'info'=>$ERROR_CODE_INFO[$code].($append_msg?"[$append_msg]":''),'data'=>[]));
    }

    /**
     * @param $data
     */
    protected function jsonReturn($data)
    {
        header('Content-Type:application/json;charset=utf-8');
        die(json_encode($data,JSON_UNESCAPED_UNICODE));
    }
}